grammar Script;

import CommonLexer;

name: Identifier;

literal
    : INTEGER_LITERAL
    | FLOAT_LITERAL
    | BOOL_LITERAL
    | NULL_LITERAL
    | STRING_LITERAL
    ;


parameters
    : '(' (name (',' name)*)? ')'
    ;

function: parameters block;

value:
    literal
  | function
  | json
  | expression
;

key: Identifier
   | squotes='"' Identifier '"'
   | dquotes= '\'' Identifier '\''
   ;


pair: key ':' value;

obj
   : '{' pair (',' pair)* '}'
   | '{' '}'
   ;

arr: '[' value (',' value)* ']'
   | '[' ']'
   ;

json: obj
    | arr
    ;


statement
    : IF parExpression block (ELSE statement)?
    | FOR '(' forControl ')' block
    | WHILE parExpression block
    | RETURN expression? (';')?
    | BREAK (';')?
    | CONTINUE (';')?
    | IMPORT importStatement ';'
    | EXPORT exportStatement
    | statExpression=expression (';')?
    | SEMI
    ;

importStatement
    : name ('.' name)*
    ;

exportStatement: json;

forControl
    : forInit? ';' expression? ';' forUpdate=expressionList?
    ;

forInit
    : expressionList
    ;

parExpression
    : '(' expression ')'
    ;

expressionList
    : expression (',' expression)*
    ;

functionCall
    : name '(' expressionList? ')'
    ;


propertyExp
        : '.' functionCall
        | '.' name
        |'[' INTEGER_LITERAL']'
        |'["' name '"]'
        |'[\'' name '\']'
        ;

//   | squotes='"' Identifier '"'
//   | dquotes= '\'' Identifier '\''
propertysExp
    :  name propertyExp*
    ;

expression
    : functionCall      //方法执行  c();
    | propertysExp
    | <assoc=right> propertysExp '=' expression
    | <assoc=right> propertysExp '=' json
    | propertysExp '=' function   //c = (){}
//    | THIS '.' expression
    |  expression postfix=('++' | '--')
    |  expression bop=('*'|'/'|'%') expression
    |  expression bop=('+'|'-') expression
    |  expression bop=('<=' | '>=' | '>' | '<' | '==' | '!=') expression
    |  expression bop=('&&' | '||') expression
//    | expression bop='?' expression ':' expression
    | <assoc=right> expression bop=('+=' | '-=' | '*=' | '/=' | '%=') expression
    | primary
    | json
    ;

primary
    : '(' expression ')'
    | literal
    ;

blockStatement
    : statement
    ;

blockStatements
    : blockStatement*
    ;

block
    : '{' blockStatements '}'
    ;

prog
    : blockStatements
    ;